#ifndef BASE_UDP_MSG_BUFFER_H_
#define BASE_UDP_MSG_BUFFER_H_
#include "ct_mutex.h"
#include "ctType.h"
#include "ctSocket.h"
#include <vector>

template <typename _type>
class UDPByteBuffer
{
        public:
                UDPByteBuffer();

                inline void Lock()
                {
                        m_Lock_.lock();
                }
                inline void UnLock()
                {
                        m_Lock_.unlock();
                }

                inline void put(const BYTE *buf,const DWORD size)
                {
                        wr_reserve(size);
                        bcopy(buf,&buffer_[curr_ptr_],size);
                        curr_ptr_ += size;
                }

                inline BYTE *wr_buf()
                {
                        return &buffer_[curr_ptr_];
                }

                inline BYTE *rd_buf()
                {
                        return &buffer_[off_ptr_];
                }

                inline bool rd_ready()
                {
                        bool ret = curr_ptr_ > off_ptr_;
                        return ret;
                }

                inline DWORD rd_size()
                {
                        DWORD ret = curr_ptr_ - off_ptr_;
                        return ret;
                }

                inline void rd_flip(DWORD size)
                {	
                        if( size == 0 ) return;
                        off_ptr_ += size;
                        if (curr_ptr_ > off_ptr_)
                        {
                                DWORD tmp = curr_ptr_ - off_ptr_;
                                if (off_ptr_ >= tmp)
                                {
                                        memmove(&buffer_[0],&buffer_[off_ptr_],tmp);
                                        off_ptr_ = 0;
                                        curr_ptr_ = tmp;
                                }
                        }
                        else
                        {
                                off_ptr_ = 0;
                                curr_ptr_ = 0;
                        }
                }

                inline DWORD wr_size()
                {
                        DWORD ret = max_size_ - curr_ptr_;
                        return ret;
                }

                inline void wr_flip(const DWORD size)
                {
                        curr_ptr_ += size;
                }

                inline void reset()
                {
                        off_ptr_ = 0;
                        curr_ptr_ = 0;
                }

                inline DWORD maxSize() const
                {
                        return max_size_;
                }

                inline void wr_reserve(const DWORD size);

        public:
                ctMutex m_Lock_;

        private:
                DWORD max_size_;
                DWORD off_ptr_;
                DWORD curr_ptr_;
                _type buffer_;

};

typedef UDPByteBuffer<std::vector<BYTE> > t_UDPBufferCmdQueue;

        template <>
inline void t_UDPBufferCmdQueue::wr_reserve(const DWORD size)
{
        if (wr_size() < size)
        {
#define trunkCount(size) (((size) + trunkSize - 1) / trunkSize)
                max_size_ += (trunkSize * trunkCount(size));
                buffer_.resize(max_size_);
        }
}
#endif //BASE_UDP_MSG_BUFFER_H_
